﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MethodWorx.CMS.Content;
using System.Web;
using MethodWorx.CMS.Membership;
using MethodWorx.CMS.Workflow;
using MethodWorx.CMS.Services;
using StructureMap;

namespace MethodWorx.CMS.Web
{
    public class CmsRequestContext : IDisposable
    {
        private Dictionary<Type, object> cache = new Dictionary<Type, object>();
        private static CmsRequestContext current;
        private IWorkflowExecutionContext workflowExecutionContext;

        public CmsRequestContext()
        {
        }

        public CmsRequestContext(bool designMode)
        {
            this.DesignMode = designMode;
        }

        public Func<IWorkflowExecutionContext> WorkflowExecutionContextFactory { get; set; }
        public IWorkflowExecutionContext WorkflowExecutionContext
        {
            get
            {
                if (this.workflowExecutionContext == null)
                    this.workflowExecutionContext = this.WorkflowExecutionContextFactory();

                return this.workflowExecutionContext;
            }
        }

        public T GetInstance<T>(Func<T> t)
        {
            if(this.cache.ContainsKey(typeof(T)))
                return (T)this.cache[typeof(T)];
            else
            {
                this.cache.Add(typeof(T), t());
                return (T)this.cache[typeof(T)];
            }
        }

        public Page Page
        {
            get;
            set;
        }

        #region IDisposable Members

        public void Dispose()
        {
            foreach (var o in this.cache.Values)
            {
                try
                {
                    if (o is IDisposable)
                        ((IDisposable)o).Dispose();
                }
                catch (ObjectDisposedException)
                {
                }
            }
        }

        public static CmsRequestContext Current
        {
            get
            {
                if (HttpContext.Current == null)
                {
                    if (current == null)
                        current = new CmsRequestContext();
                    return current;
                }
                else
                {
                    var rc = (CmsRequestContext)HttpContext.Current.Items[Constants.CMSREQUESTCONTEXTKEY]; 
                    if(rc == null)
                    {
                        rc = new CmsRequestContext();
                        rc.WorkflowExecutionContextFactory = () => new HttpWorkflowExecutionContext(HttpContext.Current, GetCurrentUser(HttpContext.Current)) ;
                        HttpContext.Current.Items[Constants.CMSREQUESTCONTEXTKEY] = rc;
                    }
                    return rc;
                }
            }
        }

        private static User GetCurrentUser(HttpContext httpContext)
        {
            Guid userId;
            if(httpContext.User == null || !Guid.TryParse(httpContext.User.Identity.Name, out userId))
            {
                return ObjectFactory.GetInstance<IUserService>().GetUserByName("host");
            }
            else
                return ObjectFactory.GetInstance<IUserService>().GetUserById(Guid.Parse(httpContext.User.Identity.Name));
        }

        #endregion

        public PreviewSession PreviewSession { get; set; }

        public bool Preview
        {
            get { return this.PreviewSession != null; }
        }

        public bool DesignMode { get; private set; }
    }
}
